package vip.wangwenhao.autoconfigure.base;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpHeaders;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger.web.*;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import vip.wangwenhao.autoconfigure.constants.Oauth2Constants;
import vip.wangwenhao.common.constants.CommonConstants;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author wangwenhao
 */
@EnableSwagger2
public class Swagger2 {

    @Value("${spring.application.name}")
    private String applicationName;

    @Value("${security.oauth2.client.client-id}")
    private String clientId;

    @Value("${security.oauth2.client.client-secret}")
    private String clientSecret;

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .groupName(applicationName)
                .select()
                .apis(RequestHandlerSelectors.basePackage(CommonConstants.BASE_PACKAGE))
                .paths(PathSelectors.any())
                .build()
                .securityContexts(Collections.singletonList(securityContext()))
                .securitySchemes(Arrays.asList(securitySchema(), apiKey(), apiCookieKey()));
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("panda cloud Api Doc")
                .description("panda cloud 接口文档")
                .termsOfServiceUrl("http://doc.wangwenhao.vip/")
                .contact(new Contact("wangwenhao", "", "itwangwh@163.com"))
                .version("1.0")
                .build();
    }

    @Bean
    public SecurityScheme apiKey() {
        return new ApiKey(HttpHeaders.AUTHORIZATION, HttpHeaders.AUTHORIZATION, "header");
    }

    @Bean
    public SecurityScheme apiCookieKey() {
        return new ApiKey(HttpHeaders.COOKIE, HttpHeaders.AUTHORIZATION, "cookie");
    }

    private OAuth securitySchema() {

        List<AuthorizationScope> authorizationScopeList = Oauth2Constants.AUTHORIZATION_SCOPE.stream().map(s -> new AuthorizationScope(s, s)).collect(Collectors.toList());
        List<GrantType> grantTypes = Arrays.asList(new ResourceOwnerPasswordCredentialsGrant(Oauth2Constants.ACCESS_TOKEN_URL));
        return new OAuth("security", authorizationScopeList, grantTypes);
    }

    private SecurityContext securityContext() {
        return SecurityContext.builder().securityReferences(defaultAuth())
                .build();
    }

    private List<SecurityReference> defaultAuth() {

        final AuthorizationScope[] authorizationScopes = Oauth2Constants.AUTHORIZATION_SCOPE.stream().map(s -> new AuthorizationScope(s, s)).collect(Collectors.toList()).toArray(new AuthorizationScope[0]);
        return Collections.singletonList(new SecurityReference("security", authorizationScopes));
    }

    @Bean
    public SecurityConfiguration security() {
        return SecurityConfigurationBuilder.builder()
                .clientId(clientId)
                .clientSecret(clientSecret)
                .realm(applicationName)
                .appName(applicationName)
                .scopeSeparator(",")
                .additionalQueryStringParams(null)
                .useBasicAuthenticationWithAccessCodeGrant(false)
                .build();
    }

    @Bean
    UiConfiguration uiConfig() {
        return UiConfigurationBuilder.builder()
                .deepLinking(true)
                .displayOperationId(false)
                .defaultModelsExpandDepth(1)
                .defaultModelExpandDepth(1)
                .defaultModelRendering(ModelRendering.EXAMPLE)
                .displayRequestDuration(false)
                .docExpansion(DocExpansion.NONE)
                .filter(false)
                .maxDisplayedTags(null)
                .operationsSorter(OperationsSorter.ALPHA)
                .showExtensions(false)
                .tagsSorter(TagsSorter.ALPHA)
                .validatorUrl(null)
                .build();
    }

}